Skip to content

Warn about arguments the callee never declared - #92

Merged
revarbat merged 1 commit into
mainfrom
warn-undeclared-arguments
Aug 13, 2026
Merged

Warn about arguments the callee never declared#92
revarbat merged 1 commit into
mainfrom
warn-undeclared-arguments

Conversation

@revarbat

Copy link
Copy Markdown
Member

Passing a named argument no parameter matches, or more positional arguments than there are parameters, was silently dropped: the call ran, the parameter kept its default, and a typo'd argument name was undetectable. Real OpenSCAD warns for both (Parameters.cc's parse_without_defaults), so this port now does too, with the same message text:

WARNING: variable b not specified as parameter in file t.scad, line 3
WARNING: Too many unnamed arguments supplied in file t.scad, line 5

Where the check goes

Five places, because none of the argument-binding paths share a choke point:

path file
bindArgs (interpreter) user_calls.cpp
buildBoundArgs, bindAstArgsIntoFrame (bytecode VM) bytecode_vm.cpp
evalModularCall (builtin modules) csg_resolve.cpp
Op::PushBuiltinWrap / Op::PushCsgWrap bytecode_vm.cpp

That last row is the one that isn't obvious: the transform/color/hull/minkowski/render/extrude/projection/offset/roof/CSG family never reaches evalModularCall once the bytecode compiler turns it into a wrap op. tests/test_unexpected_args.cpp runs every case twice — VM off and VM on — and asserts the two agree, which is what surfaced it.

Rules ported

  • $-prefixed names other than $children are exempt (isConfigVariable, mirroring ContextFrame::is_config_variable) — a $-name is a dynamic-scope override, never a parameter.
  • "Too many unnamed arguments" fires once per call, like upstream's warned_for_extra_arguments latch.
  • Builtin parameter names live in builtinParamNames (registry.cpp), each list the union of upstream's own Parameters::parse declaration and any extra name this port reads via getArg, so it never warns about an argument it goes on to honour. Add to it whenever a builtin gains a parameter.
  • Builtin functions get no entries beyond textmetrics/fontmetrics: upstream reads their arguments positionally without Parameters::parse, so sin(bogus=30) warns about nothing there (verified against 2022.08.22) and warning would be a divergence, not a fix.
  • Not ported: argument X supplied more than once and argument X overrides positional argument, separate conditions this port's simpler positional-matching rule doesn't track.

Verification

  • Message-for-message parity with OpenSCAD 2022.08.22 on a script covering user modules, user functions, function literals, nested/compiled calls, and every builtin group.
  • False-positive sweep: the 901 scripts extracted from BOSL2's own tests/*.scadtest, plus BOSL2's examples/, plus Dalek.scadzero unexpected-argument warnings from any of them.
  • Full suite green both ways: 1477/1477 with the VM off and with OSCAD_BYTECODE_VM=1.
  • No measurable render-time change on Dalek.scad.

🤖 Generated with Claude Code

Passing a named argument no parameter matches, or more positional
arguments than there are parameters, was silently dropped: the call ran,
the parameter kept its default, and a typo'd argument name was
undetectable. Real OpenSCAD warns for both (Parameters.cc's
parse_without_defaults), so this port now does too, with the same message
text.

The check has to go in five places, because none of the argument-binding
paths share a choke point: bindArgs (interpreter), buildBoundArgs and
bindAstArgsIntoFrame (bytecode VM), evalModularCall (builtin modules),
and the VM's Op::PushBuiltinWrap/Op::PushCsgWrap handlers -- the
transform/color/hull/extrude/CSG family never reaches evalModularCall
once compiled. test_unexpected_args.cpp runs every case both VM-off and
VM-on and asserts the two agree, which is what caught that last gap.

$-prefixed names other than $children stay exempt, matching
ContextFrame::is_config_variable. Builtin parameter names come from a
table in registry.cpp -- the union of upstream's own Parameters::parse
declarations and any extra name this port reads via getArg, so it never
warns about an argument it goes on to honour. Builtin functions get no
entries beyond textmetrics/fontmetrics, since upstream reads their
arguments positionally and warns about nothing.

Verified message-for-message against OpenSCAD 2022.08.22 on a script
covering user modules, user functions, function literals, nested calls
and every builtin group; and checked for false positives against the 901
scripts in BOSL2's own test suite, its examples, and Dalek.scad -- zero
warnings from any of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@revarbat
revarbat merged commit 4bcb81d into main Aug 13, 2026
3 checks passed
@revarbat
revarbat deleted the warn-undeclared-arguments branch August 13, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant